home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / pj9_3.arc / STREAM.ASM < prev    next >
Assembly Source File  |  1991-10-07  |  10KB  |  458 lines

  1.     title    stream i/o
  2.     include    asm.inc
  3.  
  4. SIO_BUFSIZ    equ    8192    ; stream io buffer size
  5.  
  6. stream_io_str struc
  7.   sio_position        dd  ?    ; stream position
  8.   sio_offset        dd  ?    ; buffer offset
  9.   sio_read_bc        dw  ?    ; buffer byte count for reading
  10.   sio_write_bc        dw  ?    ; buffer byte count for writing
  11.   sio_file_handle    dw  ?    ; dos file handle
  12.   sio_buffer        db SIO_BUFSIZ dup(?)  ; stream buffer
  13. stream_io_str ends
  14.  
  15.  
  16.     .data
  17. ertx_disk_full        db    'Disk full',0
  18. ertx_fopen_mode        db    'Bad mode in fopen',0
  19. ertx_out_of_handles    db    'Out of stream handles',0
  20. ertx_stream_handle    db    'Bad stream handle',0
  21.  
  22.     .data?
  23. stream_pointers        dd    FOPEN_MAX dup(?)
  24.  
  25.  
  26.     .code
  27.     extn    free,ms_dos,ms_dos_strerror,set_strerror,malloc
  28.     public    fclose,fopen,fread,fwrite
  29.  
  30.  
  31. ;;    fclose
  32. ;
  33. ;    entry    BX    stream handle
  34. ;    exit    Cf    if error closing file or bad handle
  35. ;    uses    AX,BX
  36. ;
  37. fclose    proc
  38.     pushm    di,si,es
  39.     call    fwrite_flush        ; write bytes left in stream buffer
  40.     jc    fcl1            ;  if disk full
  41.  
  42.     call    stream_struct_write    ; access stream structure
  43.     jc    fcl1            ;  if bad handle
  44.  
  45.     mov    si,bx            ; clear stream structure pointer
  46.     add    si,si
  47.     add    si,si
  48.     mov    wptr stream_pointers[bp+si],NULL_POINTER
  49.     mov    wptr stream_pointers[bp+si+2],NULL_POINTER
  50.  
  51.     mov    bx,es:sio_file_handle[di]
  52.     call    free
  53.  
  54.     mov    ah,3Eh
  55.     call    ms_dos_strerror
  56.  
  57. fcl1:    popm    es,si,di
  58.     ret
  59. fclose    endp
  60.  
  61.  
  62. ;;    fopen
  63. ;
  64. ;    entry    AX    mode, 'r' or 'w' to open for reading or writing
  65. ;        DS:SI    filename
  66. ;    exit    BX    stream handle
  67. ;        Cf    if error
  68. ;    uses    AX
  69. ;
  70. fopen    proc
  71.     pushm    cx,dx,di,es
  72.     cmp    ax,'r'
  73.     mov    dx,3D00h
  74.     je    fop1            ; if opening file for reading only
  75.     cmp    ax,'w'
  76.     jne    fop3            ; if not open for write (unknown mode)
  77.     mov    dh,3Ch
  78.     mov    cx,0
  79. fop1:    mov    ax,dx
  80.     mov    dx,si
  81.     call    ms_dos_strerror        ; (ms dos with error handling)
  82.     jc    fop2            ;  if file open failed
  83.     mov    dx,ax
  84.  
  85.     call    malloc_stream
  86.     jc    fop4            ;  if no memory or stream handles
  87.  
  88.     mov    al,0            ; zero stream structure (except for
  89.     mov    cx,sio_buffer        ;  buffer space)
  90.     push    di
  91.     rep    stosb
  92.     pop    di
  93.  
  94.     mov    es:sio_file_handle[di],dx
  95.     clc
  96. fop2:    popm    es,di,dx,cx
  97.     ret
  98.  
  99. fop3:    lea    ax,ertx_fopen_mode    ; *Bad mode in fopen*
  100.     call    set_strerror
  101.     jmp    fop2
  102.  
  103. fop4:    mov    ah,3Eh            ; close file, no memory for structure
  104.     mov    bx,dx
  105.     call    ms_dos
  106.     stc
  107.     jmp    fop2
  108. fopen    endp
  109.  
  110.  
  111. ;;    fread
  112. ;
  113. ;    entry    BX    stream handle
  114. ;        CX    byte count
  115. ;        ES:DI    destination pointer
  116. ;    exit    AX    actual byte count (!=CX for EOF)
  117. ;        DI    updated
  118. ;        Cf    if error
  119. ;
  120. fread    proc
  121.     pushm    di,bx,cx,dx,si,ds
  122.     cmp    bx,stdin
  123.     je    fre3            ; if special handle, standard input
  124.  
  125.     call    stream_struct_read
  126.     jc    fre4
  127.     mov    bx,si
  128.  
  129. fre1:    jcxz    fre4            ; if read finished
  130.  
  131.     mov    ax,wptr sio_position[bx]; compute stream position w/i buffer
  132.     mov    dx,wptr sio_position[bx+2]
  133.     sub    ax,wptr sio_offset[bx]
  134.     sbb    dx,wptr sio_offset[bx+2]
  135.     jnz    fre2            ;  if buffer not w/i 64k of position
  136.  
  137.     mov    dx,sio_read_bc[bx]    ; get number of bytes to end of buffer
  138.     sub    dx,ax
  139.     jbe    fre2            ;  if stream position not in buffer
  140.  
  141.     lea    si,sio_buffer[bx]
  142.     add    si,ax
  143.  
  144.     call    rep_movsb_limit
  145.  
  146.     add    wptr sio_position[bx],dx ; update stream position
  147.     adc    wptr sio_position[bx+2],0
  148.     jmp    fre1
  149.  
  150. fre2:    call    fread_primitive        ; fill stream buffer
  151.     jbe    fre4            ;  if error (Cf==1) or EOF (Zf==1)
  152.     jmp    fre1            ;  else successful
  153.  
  154. fre3:    mov    ah,3Fh            ; read from special handle stdin
  155.     mov    dx,es
  156.     mov    ds,dx
  157.     mov    dx,di
  158.     call    ms_dos_strerror
  159.     jc    fre4
  160.  
  161.     add    di,ax            ; (should not set Cf unless DI wraps)
  162.  
  163. fre4:    popm    ds,si,dx,cx,bx,ax
  164.     jc    fre5            ; if error
  165.     neg    ax            ; else return bytes read
  166.     add    ax,di
  167.     clc
  168. fre5:    ret
  169. fread    endp
  170.  
  171.  
  172. ;;    fread primitive
  173. ;
  174. ;    entry    DS:BX    stream structure
  175. ;    exit    AX    bytes read from file
  176. ;        Cf    if error (Zf unknown)
  177. ;        Zf    if end of file
  178. ;    uses    SI
  179. ;
  180. fread_primitive proc
  181.     pushm    bx,cx,dx
  182.     mov    si,bx
  183.  
  184.     mov    ax,4200h        ; position file
  185.     mov    bx,sio_file_handle[si]
  186.     mov    dx,wptr sio_position[si]
  187.     mov    cx,wptr sio_position[si+2]
  188.     call    ms_dos_strerror
  189.     jc    frp1            ;  if error position file
  190.  
  191.     mov    wptr sio_offset[si],ax
  192.     mov    wptr sio_offset[si+2],dx
  193.     mov    sio_read_bc[si],0
  194.  
  195.     mov    ah,3Fh            ; read file
  196.     mov    cx,size sio_buffer
  197.     lea    dx,sio_buffer[si]
  198.     call    ms_dos_strerror
  199.     jc    frp1            ;  if read error
  200.     mov    sio_read_bc[si],ax
  201.  
  202.     or    ax,ax            ; set Zf for end of file
  203. frp1:    popm    dx,cx,bx
  204.     ret
  205. fread_primitive endp
  206.  
  207.  
  208. ;;    fwrite
  209. ;
  210. ;    entry    BX    stream handle
  211. ;        CX    byte count
  212. ;        DS:SI    source pointer
  213. ;    exit    AX    bytes written
  214. ;        SI    updated
  215. ;        Cf    if error
  216. ;
  217. fwrite    proc
  218.     pushm    si,cx,dx,di,es
  219.     cmp    bx,stdout        ; check for special streams
  220.     je    fwr2            ;  if writing to standard out
  221.     cmp    bx,stderr
  222.     je    fwr2            ;  if writing to standard error
  223.  
  224.     call    fwrite_flush_maybe    ; flush buffer in event of seek
  225.     jc    fwr3            ;  if bad handle or disk full
  226.  
  227.     call    stream_struct_write    ; access stream structure
  228.     jc    fwr3            ;  if bad handle
  229.  
  230. fwr1:    clc
  231.     jcxz    fwr3            ;  if write complete
  232.  
  233.     mov    ax,es:sio_write_bc[di]    ; compute space left in stream buffer
  234.     mov    dx,size sio_buffer
  235.     sub    dx,ax
  236.     jb    fwr3            ;  if internal error (Cf=1)
  237.  
  238.     push    di            ; copy to stream buffer
  239.     lea    di,sio_buffer[di]
  240.     add    di,ax
  241.     call    rep_movsb_limit
  242.     pop    di
  243.  
  244.     add    ax,dx            ; update stream buffer byte count
  245.     mov    es:sio_write_bc[di],ax    ;  and position
  246.     add    wptr es:sio_position[di],dx
  247.     adc    wptr es:sio_position[di+2],0
  248.  
  249.     cmp    ax,size sio_buffer    ; check stream buffer level
  250.     jb    fwr1            ;   if not full
  251.     call    fwrite_flush        ;   else write buffer to disk
  252.     jnc    fwr1            ;     if write successful
  253.     jmp    fwr3            ;     else disk full (Cf=1)
  254.  
  255. fwr2:    mov    ah,40h            ; write standard output/error
  256.     mov    dx,si
  257.     call    ms_dos_strerror
  258.     jc    fwr3            ;  if write failed
  259.     add    si,ax
  260.  
  261. fwr3:    popm    es,di,dx,cx,ax
  262.     jc    fwr4            ; if error
  263.     neg    ax            ; else return bytes written
  264.     add    ax,si
  265.     clc
  266. fwr4:    ret
  267. fwrite    endp
  268.  
  269.  
  270. ;;    fwrite flush
  271. ;
  272. ;    entry    BX    stream handle
  273. ;    exit    Cf    if disk full, bad handle, or other error
  274. ;    uses    AX
  275. ;
  276. fwrite_flush proc
  277.     pushm    bx,cx,dx,si,ds
  278.     call    stream_struct_read
  279.     jc    fwf1            ;  if bad handle
  280.  
  281.     mov    cx,sio_write_bc[si]
  282.     jcxz    fwf1            ;  if buffer empty (nothing to flush)
  283.  
  284.     mov    ax,4200h        ; position file
  285.     mov    bx,sio_file_handle[si]
  286.     mov    dx,wptr sio_offset[si]
  287.     mov    cx,wptr sio_offset[si+2]
  288.     call    ms_dos_strerror
  289.     jc    fwf1            ;  if position failed
  290.  
  291.     mov    ah,40h            ; write file
  292.     mov    cx,sio_write_bc[si]
  293.     lea    dx,sio_buffer[si]
  294.     call    ms_dos_strerror
  295.     jc    fwf1            ;  if write failed
  296.  
  297.     add    wptr sio_offset[si],ax    ; update buffer position
  298.     adc    wptr sio_offset[si+2],0
  299.     mov    sio_write_bc[si],0    ; clear output byte count
  300.  
  301.     cmp    ax,cx
  302.     je    fwf1            ;  if correct byte cnt written (Cf=0)
  303.  
  304.     lea    ax,ertx_disk_full    ;  else *Disk full*
  305.     call    set_strerror
  306.  
  307. fwf1:    popm    ds,si,dx,cx,bx
  308.     ret
  309. fwrite_flush endp
  310.  
  311.  
  312. ;;    fwrite flush maybe
  313. ;
  314. ;    entry    BX    stream handle
  315. ;    exit    Cf    if bad handle or disk full
  316. ;    uses    AX,DX
  317. ;
  318. fwrite_flush_maybe proc
  319.     pushm    si,ds
  320.     call    stream_struct_read
  321.     jc    ffm2            ;  if bad stream handle
  322.  
  323.     mov    ax,wptr sio_offset[si]    ; compute buffer position
  324.     mov    dx,wptr sio_offset[si+2]
  325.     add    ax,sio_write_bc[si]
  326.     adc    dx,0
  327.  
  328.     cmp    ax,wptr sio_position[si]
  329.     jne    ffm1            ;  if wrong position
  330.     cmp    dx,wptr sio_position[si+2]
  331.     je    ffm2            ;  if right position
  332.  
  333. ffm1:    call    fwrite_flush
  334.     jc    ffm2            ;  if disk full
  335.  
  336.     mov    ax,wptr sio_position[si] ; reposition buffer
  337.     mov    wptr sio_offset[si],ax
  338.     mov    ax,wptr sio_position[si+2]
  339.     mov    wptr sio_offset[si+2],ax
  340.  
  341. ffm2:    popm    ds,si
  342.     ret
  343. fwrite_flush_maybe endp
  344.  
  345.  
  346. ;;    malloc stream
  347. ;
  348. ;    exit    BX    stream handle
  349. ;        ES:DI    stream structure
  350. ;        Cf    if no handles or memory left
  351. ;    uses    AX
  352. ;
  353. malloc_stream proc
  354.     pushm    cx,si
  355.     mov    bx,stderr        ; find free stream handle
  356. mas1:    inc    bx
  357.     cmp    bx,FOPEN_MAX
  358.     jae    mas3            ;  if no handles left
  359.  
  360.     mov    si,bx
  361.     add    si,si
  362.     add    si,si
  363.     les    di,stream_pointers[bp+si]
  364.     mov    ax,es
  365.     or    ax,di
  366.     jnz    mas1            ;  if stream allocated
  367.  
  368.     mov    cx,size stream_io_str    ; allocate memory for stream structure
  369.     call    malloc
  370.     jc    mas2            ;  if no memory
  371.  
  372.     mov    wptr stream_pointers[bp+si],di
  373.     mov    wptr stream_pointers[bp+si+2],es
  374.  
  375. mas2:    popm    si,cx
  376.     ret
  377.  
  378. mas3:    lea    ax,ertx_out_of_handles    ; *Out of stream handles*
  379.     call    set_strerror
  380.     jmp    mas2
  381. malloc_stream endp
  382.  
  383.  
  384. ;;    rep movsb limit
  385. ;
  386. ;    entry    DS:SI    source pointer
  387. ;        ES:DI    destination pointer
  388. ;        CX    byte count
  389. ;        DX    byte count limit
  390. ;    exit    SI,DI    updated
  391. ;        CX    updated (nonzero if original DX<CX)
  392. ;        DX    actual number of bytes transfered (minimum of CX,DX)
  393. ;
  394. rep_movsb_limit proc
  395.     push    ax
  396.     cmp    cx,dx            ; DX is unsigned minimum of CX and DX
  397.     ja    rmm1
  398.     mov    dx,cx
  399.  
  400. rmm1:    mov    ax,cx            ; this procedure implements a smart
  401.     sub    ax,dx            ;  "rep movsb" instruction.  the
  402.     mov    cx,dx            ;  difference is it moves the minimum
  403.     rep    movsb            ;  number of bytes specified in CX or
  404.     mov    cx,ax            ;  DX.  CX is updated normally; DX has
  405.     pop    ax            ;  the actual number of bytes moved.
  406.     ret
  407. rep_movsb_limit endp
  408.  
  409.  
  410. ;;    stream struct read
  411. ;
  412. ;    entry    BX    stream handle
  413. ;    exit    DS:SI    stream structure
  414. ;        Cf    if bad handle
  415. ;    uses    AX
  416. ;
  417. stream_struct_read proc
  418.     cmp    bx,FOPEN_MAX
  419.     jae    rss1            ;  if handle too large
  420.     mov    si,bx
  421.     add    si,si
  422.     add    si,si
  423.     lds    si,stream_pointers[bp+si]
  424.     mov    ax,ds
  425.     or    ax,si
  426.     jz    rss1            ;  if inactive stream
  427.     ret
  428.  
  429. rss1:    lea    ax,ertx_stream_handle    ; *Bad stream handle*
  430.     jmp    set_strerror
  431. stream_struct_read endp
  432.  
  433.  
  434. ;;    stream struct write
  435. ;
  436. ;    entry    BX    stream handle
  437. ;    exit    ES:DI    stream structure
  438. ;        Cf    if bad handle
  439. ;    uses    AX
  440. ;
  441. stream_struct_write proc
  442.     cmp    bx,FOPEN_MAX
  443.     jae    wss1            ;  if handle too large
  444.     mov    di,bx
  445.     add    di,di
  446.     add    di,di
  447.     les    di,stream_pointers[bp+di]
  448.     mov    ax,es
  449.     or    ax,di
  450.     jz    wss1            ;  if inactive stream
  451.     ret
  452.  
  453. wss1:    lea    ax,ertx_stream_handle    ; *Bad stream handle*
  454.     jmp    set_strerror
  455. stream_struct_write endp
  456.  
  457.     end
  458.